# -*- coding:utf-8 -*-

from __future__ import unicode_literals
from __future__ import absolute_import
from __future__ import division

import re
import xlrd
from functools import reduce

from pickle import load
from kgpipeline.util import save_pickle
from argparse import ArgumentParser

from kgpipeline.logger import setup_default_logging

import logging

logger = logging.getLogger(__name__)

RE_SPLIT = re.compile(r' or |／|\n', re.MULTILINE)


def excel2num(x):
    return reduce(lambda s, a: s * 26 + ord(a) - ord('A') + 1, x, 0)


def main(xlsx_name, pkl_name, altname_column_index, verbose=False):
    with open(pkl_name) as f:
        schema = load(f)

    plist = schema["plist"]
    slinks = schema["slinks"]

    work_book = xlrd.open_workbook(xlsx_name)
    sheet = work_book.sheet_by_name('template')

    for row_i in range(2, sheet.nrows):
        # 源字段， cnSchema字段
        version = sheet.cell_value(row_i, 0)
        if version is not None and version.startswith("v"):
            entity_type = sheet.cell_value(row_i, 4)
            if not entity_type:
                continue
            # schema name
            schema_field = sheet.cell_value(row_i, 5).strip()
            if schema_field in ['in', 'out']:
                continue
            # alternateName
            source_field = RE_SPLIT.split(sheet.cell_value(row_i, altname_column_index).strip())
            source_field_list = [i.strip().lower() for i in source_field if i.strip()]
            if not source_field_list:
                continue
            if not plist.get(entity_type):
                logger.info("Warning: No type {0} in schema {1}!".format(entity_type, schema["name"]))
                continue
            props = plist[entity_type]
            if schema_field not in props:
                if schema_field not in slinks:
                    logger.info("Warning: No property {0} in schema {1} for type {2}"
                                .format(schema_field, schema["name"], entity_type))
                continue
            if verbose:
                logger.info("Info: Patch property {0} of type {1} with {2} in schema {3}"
                            .format(schema_field, entity_type, "|".join(source_field_list), schema["name"]))
            props[schema_field]["alt"].update(source_field_list)

    save_pickle(schema, pkl_name + ".new")


if __name__ == '__main__':
    parser = ArgumentParser(description="patch existing schema with data source property aliases")
    parser.add_argument("excel", help="schema excel")
    parser.add_argument("pkl", help="schema pkl generated from jsonld")
    parser.add_argument("-c", "--column", help="column number or name of the alternate names")
    parser.add_argument("-v", "--verbose", action="store_true", help="show extra information")
    args = parser.parse_args()

    setup_default_logging()

    column_index = -1

    try:
        column_index = int(args.column) - 1
    except ValueError:
        column_index = excel2num(args.column)

    main(args.excel, args.pkl, column_index, args.verbose)
